import express from "express";
import path from "path";
import fs from "fs";
import cors from "cors";
import { pathToFileURL } from 'url';  // 新增顶部导入
import config from "./core/config.js";
import {bindClass,createKnex,loadWebToEnd} from "./core/helper.js";



import Service from "./core/lib/service.js";
import cache from './core/lib/cache.js';
import core from "./core/lib/index.js";
import extend from "./core/lib/extend.js";
/**
 * @description 基于express封装的mvc框架，遵循约定优于配置原则
 */
class Chan {
  static helper = {};
  static modules = {};
  static plugins = {};
  static config = config;
  static cache = cache;

 
  constructor() {
    this.app = express();
    this.router = express.Router();
  }

  async init() {
    extend(this.app);
    await this.loadConfig();
    await this.loadExtends();
    this.loadCore();
    this.loadDB();
    this.loadCors();
  }

  extend(name, fn) {
    this.app.plus[name] = ()=>fn;
  }


  async loadConfig() {
    const configPath = path.join(Chan.config.APP_PATH, "config/index.js");
    if (fs.existsSync(configPath)) {
      const configUrl = pathToFileURL(configPath).href; // 新增转换
      const configModule = await import(configUrl);     // 使用 URL 导入
      Chan.config = { ...Chan.config, ...configModule.default }; // 注意 default
    }
  }

  async loadExtends() {
    const extendPath = path.join(Chan.config.APP_PATH, "extend");
    if (fs.existsSync(extendPath)) {
      const files = fs.readdirSync(extendPath).filter(file => file.endsWith(".js"));
      for (const file of files) {
        const filePath = path.join(extendPath, file);
        const fileUrl = pathToFileURL(filePath).href;  // 转换路径
        const helperModule = await import(fileUrl);    // 使用 URL 导入
        Chan.helper[file.replace(".js", "")] = helperModule?.default || helperModule; // 注意 default
      }
    }
  }

  /**
   * @description app核心模块：日志、favicon 图标、cookie、json、url、模板引擎、静态资源
   */
  loadCore() {
    core(this.app, Chan.config);
  }

  //数据库操作
  loadDB() {
    if(Chan.config?.db?.length > 0){
      Chan.config.db.map((item,index) => {
        if(index ==0){
          Chan.knex = createKnex(item);
        }else{
          Chan[`knex${index}`] = createKnex(item);
        }
      })
      Chan.Service = Service;
    }
  }

  //开始启动
  beforeStart(cb) {
    cb && cb();
  }
  //启动
  async start(cb) {
    await this.init();
    await this.loadPlugins();
    await this.loadModules();
    await this.loadCommonRouter();
    cb && cb();
  }

  //解决跨域
  loadCors() {
    Chan.config?.cors?.origin && this.app.use(cors(Chan.config.cors));
  }

  // 加载插件
  async loadPlugins() {
   await this.loadModules("plugins");
  }

  /**
   * @description 模块加载入口（路由&控制器& 服务）
   */
  async loadModules(modules = "modules") {
    const configPath = path.join(Chan.config.APP_PATH, modules);
    if (fs.existsSync(configPath)) {
      const dirs = loadWebToEnd(Chan.config[modules]);
      Chan[modules] = {};
  
      // 先加载所有服务
      for (const item of dirs) {
        Chan[modules][item] = {
          service: {},
          controller: {},
        };
        await this.loadServices(modules, item); // 确保每个模块的服务加载完成
      }
  
      // 加载控制器和路由
      for (const item of dirs) {
        await this.loadModule(modules, item); // 确保每个模块的加载完成
      }
    }
  }
  

  /**
   * @description 加载模块，包括 controller service router
   * @param {String} moduleName 模块名称
   */
  async loadModule(modules, moduleName) {
    await this.loadControllers(modules, moduleName); // 确保控制器加载完成
    await this.loadRoutes(modules, moduleName); // 然后加载路由
  }

  async loadFiles(modules, moduleName, type) {
    const dir = path.join(Chan.config.APP_PATH, modules, moduleName, type);
    if (fs.existsSync(dir)) {
      const files = fs.readdirSync(dir).filter(file => file.endsWith(".js"));
      for (const file of files) { // 使用 for...of 确保异步操作顺序
        const filePath = path.join(dir, file);
        const fileUrl = pathToFileURL(filePath).href;
        const module = await import(fileUrl);
        const name = file.replace(".js", "");
        Chan[modules][moduleName][type][name] = { ...bindClass(module.default) };
      }
    }
  }

  /**
   * @description 扫描模块下所有service
   * @param {*} moduleDir 模块路径
   * @param {*} moduleName 模块名称
   */
  async loadServices(modules, moduleName) {
   await this.loadFiles(modules, moduleName, "service");
  }

  /**
   * @description 扫描模块下所有controller
   * @param {*} moduleDir 模块路径
   * @param {*} moduleName 模块名称
   */
  async loadControllers(modules, moduleName) {
    await this.loadFiles(modules, moduleName, "controller");
  }

  /**
   * @description 扫描模块下所有router.js
   * @param {*} moduleDir 模块路径
   * @param {*} moduleName 模块名称
   */
  async loadRoutes(modules, moduleName) {
    const routersDir = path.join(Chan.config.APP_PATH, modules, moduleName, "router.js");
    if (fs.existsSync(routersDir)) {
      const routeUrl = pathToFileURL(routersDir).href; // 转换路径
      const routes = await import(routeUrl);           // 使用 URL 导入
      routes.default({ router: this.router, modules: Chan[modules], app: this.app });
    }
  }

  //通用路由，加载错误处理和500路由和爬虫处理
  async loadCommonRouter() {
    try {
      const baseRouterPath = path.join(Chan.config.APP_PATH, "router.js");
      if (fs.existsSync(baseRouterPath)) {
        const routerUrl = pathToFileURL(baseRouterPath).href; // 转换路径
        const _router = await import(routerUrl);              // 使用 URL 导入
        _router.default(this.app, this.router, Chan.config);  // 注意 default
      }
    } catch (error) {
      console.log(error);
    }
  }

  run(cb) {
    const port = Chan.config.port || "81";
    this.app.listen(port, () => {
      cb?cb(port):console.log(`Server is running on port ${port}`);
    });
  }
}
global.Chan = Chan;
export default Chan;
